unit googleTranslator;

interface

uses
  IdThread,
  IdComponent,
  IdSync,
  Controls,
  Classes,
  cxGridCustomTableView,
  SysUtils,
  GTranslate;

type

  Operations = (OpWriteLogMes,OpSaveLog,OpOnWork, opReturnRes, opSaveResult,opSuspendTimer);

  TTransSync = class(TidSync)
  public
    Operation : Operations;
    Value: String;
    iVal : Integer;
    FName : string;
    FID : string;
    FTable : string;
    FTextObj : TObject;
    WorkMode: TWorkMode;
    procedure DoSynchronize; override;
    procedure SaveResult(ItemID, ItemField, Table, res_string: string; TrTextObj: TObject);
    procedure ReturnResult(res_string: string; TrTextObj: TObject);
    procedure SuspendTimer;
  end;

  TTranslateThread =  class(TidThread)
  private
     // Private declarations
     FItemID         : String;
     FItemField      : string;
     FItemTable      : string;
     FSource        : string;
     FresultString  : string;
     FSourceLang    : TLanguageEnum;
     FDestLang      : TLanguageEnum;
     FSyncObj       : TTransSync;
     FTagObj        : TObject;
     FSender        : TcxCustomGridTableItem;
     FRecord        : TcxCustomGridRecord;
     FTranslator    : TTranslator;
  protected
     // Protected declarations
     procedure OnTranslate(const SourceStr, TranslateStr: string; LangDetected: TLanguageEnum);
     procedure OnTranslateError(const Code: Integer; Status: string);
     function EncodeTrString(Source: string):string;
  public
     // Public declarations
     property SourceString : string read FSource write FSource;
     property ResultString : string read FresultString;
     property SourceLang : TLanguageEnum read FSourceLang write FSourceLang;
     property DestLang  : TLanguageEnum read FDestLang write FDestLang;
     property ItemID : string read FItemID write FItemID;
     property ItemField : string read FItemField write FItemField;
     property ItemTable : string read FItemTable write FItemTable;
     property TagObj    : TObject read FTagObj write FTagObj;
     property YSender : TcxCustomGridTableItem read FSender write FSender;
     property YRecord : TcxCustomGridRecord read FRecord write FRecord;
     // methods
     constructor  Create(ACreateSuspended: Boolean);
     destructor Destroy; override;
     procedure Run; override;
  end;

implementation

uses uMain, DB, cxDBEdit,cxMemo , HotLog;

{ TTranslateThread }

constructor TTranslateThread.Create(ACreateSuspended: Boolean);
var inireaderrormsg : string;
begin
  inherited Create(true);
  FSyncObj := TTransSync.Create(Self);
  FTranslator := TTranslator.Create(nil);
  FTranslator.OnTranslate := OnTranslate;
  FTranslator.OnTranslateError := OnTranslateError;
  FDestLang := lng_ja;
  FSourceLang := lng_en;
  FreeOnTerminate := True;
  FTagObj := nil;
end;

destructor TTranslateThread.Destroy;
begin
  FSyncObj.Free;
  FTranslator.Free;
  inherited;
end;

function TTranslateThread.EncodeTrString(Source: string): string;
var i,p: Integer;
    tmp : string;
begin
  result := Source;
  p := Pos('&#',result);
  while p>0 do begin
    tmp:='';
    for I := p+2 to Length(result) do begin
      if result[i]=';' then Break;
      if not(result[i] in ['0'..'9']) then raise Exception.Create('Encode eror during translation');
      tmp := tmp+result[i];
    end;
    result:=StringReplace(result,'&#'+tmp+';',Chr(StrToInt(tmp)),[rfReplaceAll]);
    p := Pos('&#',result);
  end;
  { TODO : insert &amp &lt etc features }
end;

procedure TTranslateThread.Run;
var res: string;
begin
  inherited;
  try
    FTranslator.SourceLang := FSourceLang;
    FTranslator.DestLang := FDestLang;
    if Length(FSource)>0 then begin
      hLog.Add(Format('{hms} ThreadID %d - GoogleTranslate start',[Self.ThreadID]));
      FTranslator.Translate(FSource);
      hLog.Add(Format('{hms} ThreadID %d - GoogleTranslate end',[Self.ThreadID]));
    end
    else hLog.AddError(0,'GoogleTranslate',['source string is empty']);
  finally
    Stop;
  end;
end;

procedure TTranslateThread.OnTranslate(const SourceStr, TranslateStr: string;
  LangDetected: TLanguageEnum);
var tmp: string;
begin
  tmp := EncodeTrString(TranslateStr);
  FSyncObj.SaveResult(FItemID, FItemField, FItemTable, tmp,FTagObj);
  FSyncObj.ReturnResult(tmp,FTagObj);
end;

procedure TTranslateThread.OnTranslateError(const Code: Integer; Status: string);
begin
  hLog.AddError(Code,'TranslateError',[Status]);
  with FSyncObj do SuspendTimer;
end;

{ TTransSync }

procedure TTransSync.DoSynchronize;
var i: Integer;
    tmpfield :TField;
    tmpfiledname : string;
    tmpdataset : TDataSet;
begin
  inherited;
  case Operation of
    opSaveResult : with Thread as TTranslateThread do begin
        fmMain.SaveTranslations(FTable,FItemField,FItemID,Value,self.Thread as TTranslateThread);
        fmMain.tmrTranslate.Interval := 1500;
      end;
    opReturnRes : begin
        with Thread as TTranslateThread do
        if FTextObj<>nil then begin
          if FTextObj.ClassName = 'TcxDBMemo' then begin
            (TagObj as TcxDBMemo).Text := Value;
          end;
          if FTextObj.ClassName = 'TcxMemo' then begin
            (TagObj as TcxMemo).Text := Value;
          end;
        end;
      end;
    opSuspendTimer : fmMain.tmrTranslate.Interval := 600000;
  end;
end;

procedure TTransSync.SaveResult(ItemID, ItemField, Table, res_string: string; TrTextObj: TObject);
begin
  Value := res_string;
  FName := ItemField;
  FID := ItemID;
  FTable := Table;
  FTextObj := TrTextObj;
  Operation := opSaveResult;
  Synchronize;
end;

procedure TTransSync.SuspendTimer;
begin
  Operation := opSuspendTimer;
  Synchronize;
end;

procedure TTransSync.ReturnResult(res_string: string; TrTextObj: TObject);
begin
  Value := res_string;
  FTextObj := TrTextObj;
  Operation := opReturnRes;
  Synchronize;
end;

end.
